package controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"sport_booking/middleware"
	"sport_booking/models"
	"sport_booking/utils"
	"sport_booking/utils/message"
)

/*
用户第一次注册(json方式)
*/
func UserRegisterByJSON(c *gin.Context) {
	var user models.User
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	switch {
	case utils.VerifyAuthCodeFormat(user.Code) == false:
		message.SendMsg(c, message.ErrorAuthUserCode)
	case utils.VerifyNickFormat(user.Nick) == false:
		message.SendMsg(c, message.ErrorAuthUserNick)
	case utils.VerifyEmailFormat(user.Email) == false:
		message.SendMsg(c, message.ErrorAuthUserEmail)
	case utils.VerifyPasswordFormat(user.Password) == false:
		message.SendMsg(c, message.ErrorAuthUserPassword)
	default:
		// 检查验证码
		codeKey := fmt.Sprintf("%s_%s", "zc", user.Email)
		codeValue, status := models.GetCodeValue(codeKey)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		if user.Code != codeValue {
			message.SendMsg(c, message.ErrorAuthCode)
			return
		}
		// 检查昵称
		status = models.CheckNickCount(user.Nick)
		if status != message.SuccessNickNotExist {
			message.SendMsg(c, status)
			return
		}
		// 检查邮箱
		status = models.CheckEmailCount(user.Email)
		if status != message.SuccessEmailNotExist {
			message.SendMsg(c, status)
			return
		}
		// 加密密码
		encryptPassword, status := models.EncryptPassword(user.Password)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		// 添加用户
		user.Password = encryptPassword // 加密后的密码
		user.UUID = utils.GetUUID()
		// 根据uuid生成token
		token, status := middleware.GenToken(user.UUID)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		user.CreateStamp = utils.GetTimeStamp()
		user.Role = "user"
		status = models.AddUserInfo(&user)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		models.RemoveCodeValue(codeKey)
		message.SendMsg(c, message.SUCCESS, token)
	}

}

/*
发送注册验证码(json方式)
*/
func SendRegisterAuthCodeByJSON(c *gin.Context) {
	var user models.User
	var status int
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	switch {
	case utils.VerifyNickFormat(user.Nick) == false:
		message.SendMsg(c, message.ErrorAuthUserNick)
	case utils.VerifyEmailFormat(user.Email) == false:
		message.SendMsg(c, message.ErrorAuthUserEmail)
	default:
		// 检查昵称
		status = models.CheckNickCount(user.Nick)
		if status != message.SuccessNickNotExist {
			message.SendMsg(c, status)
			return
		}
		// 检查邮箱
		status = models.CheckEmailCount(user.Email)
		if status != message.SuccessEmailNotExist {
			message.SendMsg(c, status)
			return
		}

		codeKey := fmt.Sprintf("%s_%s", "zc", user.Email)
		// 读取发送次数
		countKey := fmt.Sprintf("%s_%s", "zc_count", user.Email)
		countValue, status := models.GetCodeValue(countKey)
		if status != message.ErrorNoAuthKey && countValue >= 5 {
			message.SendMsg(c, message.ErrorAuthCodeCount)
			return
		}
		// redis 写验证码
		authCode := utils.GetAuthCode()
		status = models.SetCode(codeKey, authCode, 5)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		// 邮箱发送验证码
		body := fmt.Sprintf("【运动管家】您的验证码是:%d(运动管家注册验证码),请在5分钟内完成注册。如非本人操作请忽略。", authCode)
		status = utils.SendMail("运动管家", "用户注册", body, user.Email)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		// 存储发送次数做限流
		countValue += 1
		models.SetCode(countKey, countValue, 1)
		message.SendMsg(c, message.SUCCESS)
	}

}

/*
发送重置密码验证码(json方式)
*/
func SendResetPasswordCodeByJSON(c *gin.Context) {
	var user models.User
	var status int
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	if utils.VerifyEmailFormat(user.Email) == false {
		message.SendMsg(c, message.ErrorAuthUserEmail)
		return
	}
	// 检查邮箱
	status = models.CheckEmailCount(user.Email)
	if status != message.SuccessEmailExist {
		message.SendMsg(c, status)
		return
	}

	codeKey := fmt.Sprintf("%s_%s", "cz", user.Email)
	// 读取发送次数
	countKey := fmt.Sprintf("%s_%s", "cz_count", user.Email)
	countValue, status := models.GetCodeValue(countKey)
	if status != message.ErrorNoAuthKey && countValue >= 5 {
		message.SendMsg(c, message.ErrorAuthCodeCount)
		return
	}
	authCode := utils.GetAuthCode()
	status = models.SetCode(codeKey, authCode, 5)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	// 邮箱发送验证码
	body := fmt.Sprintf("【运动管家】您的验证码是:%d(运动管家密码重置验证码),请在5分钟内完成重置。如非本人操作请忽略。", authCode)
	status = utils.SendMail("运动管家", "密码重置", body, user.Email)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	// 存储发送次数做限流
	countValue += 1
	models.SetCode(countKey, countValue, 1)
	message.SendMsg(c, message.SUCCESS)
}

/*
通过邮箱找回密码(json表单方式)
*/
func ResetPasswordByJSON(c *gin.Context) {
	var user models.User
	var status int
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	switch {
	case utils.VerifyAuthCodeFormat(user.Code) == false:
		message.SendMsg(c, message.ErrorAuthUserCode)
	case utils.VerifyEmailFormat(user.Email) == false:
		message.SendMsg(c, message.ErrorAuthUserEmail)
	case utils.VerifyPasswordFormat(user.Password) == false:
		message.SendMsg(c, message.ErrorAuthUserPassword)
	default:
		status = models.CheckEmailCount(user.Email)
		if status != message.SuccessEmailExist {
			message.SendMsg(c, status)
			return
		}
		codeKey := fmt.Sprintf("%s_%s", "cz", user.Email)
		codeValue, status := models.GetCodeValue(codeKey)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		if user.Code != codeValue {
			message.SendMsg(c, message.ErrorAuthCode)
			return
		}
		encryptPassword, status := models.EncryptPassword(user.Password)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		user.UpdateStamp = utils.GetTimeStamp()
		user.Password = encryptPassword
		status = models.UpdatePasswordByEmail(&user)
		if status != message.SUCCESS {
			message.SendMsg(c, status)
			return
		}
		models.RemoveCodeValue(codeKey)
		message.SendMsg(c, message.SUCCESS)
	}

}

/*
通过用户名密码登录(json表单方式)
*/
func UserLoginByJSON(c *gin.Context) {
	var user models.User
	var status int
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	if utils.VerifyNickFormat(user.Account) == false && utils.VerifyEmailFormat(user.Account) == false {
		message.SendMsg(c, message.ErrorCheckUserAccount)
		return
	}
	if utils.VerifyPasswordFormat(user.Password) == false {
		message.SendMsg(c, message.ErrorCheckUserPassword)
		return
	}
	if utils.VerifyNickFormat(user.Account) == true {
		// 检查昵称
		status = models.CheckNickCount(user.Account)
		if status != message.SuccessNickExist {
			message.SendMsg(c, status)
			return
		}
	}
	if utils.VerifyEmailFormat(user.Account) == true {
		// 检查邮箱
		status = models.CheckEmailCount(user.Account)
		if status != message.SuccessEmailExist {
			message.SendMsg(c, status)
			return
		}
	}
	encryptPassword, status := models.EncryptPassword(user.Password)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	uuid, status := models.GetUserUUIDB(user.Account, encryptPassword)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	tokenString, status := middleware.GenToken(uuid)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	message.SendMsg(c, message.SUCCESS, tokenString)
}

/*
通过token完善用户信息
*/
func PerfectUserInfoByJSON(c *gin.Context) {
	var user models.User
	var status int
	err := c.ShouldBindJSON(&user)
	if err != nil {
		message.SendMsg(c, message.ErrorBindData)
		return
	}
	if user.Sex == "" || user.Department == "" || user.Job == "" ||
		utils.VerifyNameFormat(user.Name) == false || utils.VerifyDateFormat(user.Birthday) == false {
		message.SendMsg(c, message.ErrorDataFormat)
		return
	}
	user.UUID = c.GetString("uuid")
	user.UpdateStamp = utils.GetTimeStamp()

	status = models.PerfectUserInfoByUUID(&user)
	if status != message.SUCCESS {
		message.SendMsg(c, status)
		return
	}
	message.SendMsg(c, message.SUCCESS)
}
